package org.lt.cj.core;

import java.util.ArrayList;
import org.lt.cj.config.entities.ConfigModel;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.htmlparser.Node;
import org.htmlparser.NodeFilter;
import org.htmlparser.Parser;
import org.htmlparser.filters.NodeClassFilter;
import org.htmlparser.filters.OrFilter;
import org.htmlparser.tags.LinkTag;
import org.htmlparser.util.NodeList;
import org.htmlparser.util.ParserException;
import org.lt.cj.config.util.RegCheck;
import org.lt.cj.core.filters.CustomCategoryFilter;
import org.lt.cj.core.filters.FrameNodeFilterImpl;
import org.lt.cj.core.utils.HttpAccesser;

public class HtmlParserTool {

    private ConfigModel configModel;

    public HtmlParserTool(ConfigModel configModel) {

        this.configModel = configModel;
    }

    public Set<String> fetchLinks(String url, LinkFilter filter) {

        Set<String> links = new HashSet<String>();
        try {
            Parser parser = new Parser(url);
            parser.setEncoding(configModel.getPageEncoding());
            NodeFilter frameFilter = new FrameNodeFilterImpl();// 过滤 <frame >标签的 filter，用来提取 frame 标签里的 src 属性所表示的链接
            // OrFilter 来设置过滤 <a> 标签，和 <frame> 标签
            OrFilter linkFilter = new OrFilter(new NodeClassFilter(LinkTag.class), frameFilter);
            // 得到所有经过过滤的标签
            NodeList list = parser.extractAllNodesThatMatch(linkFilter);
            for (int i = 0; i < list.size(); i++) {
                Node tag = list.elementAt(i);
                if (tag instanceof LinkTag)// <a> 标签
                {
                    LinkTag link = (LinkTag) tag;
                    String linkUrl = link.getLink();// url
                    if (filter.accept(linkUrl)) {                               //remove && checkURL(linkUrl)

                        links.add(linkUrl);
                    }
                } else// <frame> 标签
                {
                    // 提取 frame 里 src 属性的链接如 <frame src="test.html"/>
                    String frame = tag.getText();
                    int start = frame.indexOf("src=");
                    frame = frame.substring(start);
                    int end = frame.indexOf(" ");
                    if (end == -1) {
                        end = frame.indexOf(">");
                    }
                    String frameUrl = frame.substring(5, end - 1);
                    if (filter.accept(frameUrl)) {                              //remove && checkURL(frameUrl)
                        links.add(frameUrl);
                    }
                }
            }
            list = null;
            if (parser != null) {
                parser.setInputHTML("");
            }
            parser = null;

        } catch (ParserException e) {
            e.printStackTrace();
        }
        return links;
    }

    public List<Seed> fetchSeeds(Seed seedUrl, LinkFilter filter) {

        if (seedUrl == null) {
            return null;
        }
        String url = seedUrl.getUrl();
        List<Seed> seeds = new ArrayList();
        HttpAccesser accesser = HttpAccesser.getInstance();//获取访问http地址的工具类
        String htmlText = accesser.accessWebPage(url);
        try {
            Parser parser = new Parser();
            parser.setInputHTML(htmlText);
            parser.setEncoding(configModel.getPageEncoding());
            //自定义的分类过滤器
            CustomCategoryFilter cateFilter = new CustomCategoryFilter(configModel);
            String category = cateFilter.filtCategory(htmlText);
            if (category.trim().equals("")) {
                System.out.println("nocate" + url);
            }
            NodeFilter frameFilter = new FrameNodeFilterImpl();// 过滤 <frame >标签的 filter，用来提取 frame 标签里的 src 属性所表示的链接
            // OrFilter 来设置过滤 <a> 标签，和 <frame> 标签
            OrFilter linkFilter = new OrFilter(new NodeClassFilter(LinkTag.class), frameFilter);
            // 得到所有经过过滤的标签
            NodeList list = parser.extractAllNodesThatMatch(linkFilter);
            for (int i = 0; i < list.size(); i++) {
                Node tag = list.elementAt(i);
                if (tag instanceof LinkTag)// <a> 标签
                {
                    LinkTag link = (LinkTag) tag;
                    String linkUrl = link.getLink();// url207
                    if (filter.accept(linkUrl)) {   //remove && checkURL(linkUrl)
                        Seed seed = new Seed();
                        seed.setUrl(linkUrl);
                        seed.setSeedName(link.getLinkText());
                        RegCheck regCheck = RegCheck.getInstance();
                        if (regCheck.checkCategory(seedUrl, seed, configModel)) {
                            seed.setParentSeed(seedUrl);
                            seed.setSortName(category);
                        }
                        seeds.add(seed);
                    }
                } else {
                    // <frame> 标签
                    // 提取 frame 里 src 属性的链接如 <frame src="test.html"/>
                    String frame = tag.getText();
                    int start = frame.indexOf("src=");
                    frame = frame.substring(start);
                    int end = frame.indexOf(" ");
                    if (end == -1) {
                        end = frame.indexOf(">");
                    }
                    String frameUrl = frame.substring(5, end - 1);
                    if (filter.accept(frameUrl)) {                              //remove && checkURL(frameUrl)
                        Seed seed = new Seed();
                        seed.setUrl(frameUrl);
                        seeds.add(seed);
                    }
                }
            }
            list = null;
            if (parser != null) {
                parser.setInputHTML("");
            }
            parser = null;
        } catch (ParserException e) {
            e.printStackTrace();
        }
        return seeds;
    }

    public boolean checkURL(String linkUrl) {

        List<String> fitURLs = configModel.getFitUrlRegs();
        for (int i = 0; i < fitURLs.size(); i++) { //循环检查传入的linkUrl是否符合匹配规则

            if (linkUrl.startsWith(fitURLs.get(i))) {
                return true;
            }
        }
        return false;
    }

    public ConfigModel getConfigModel() {
        return configModel;
    }

    public void setConfigModel(ConfigModel configModel) {
        this.configModel = configModel;
    }
}
